/** 线段转path
 *
 * @param x1 端点a的x坐标
 * @param y1 端点a的y坐标
 * @param x2 x方向相对距离
 * @param y2 y方向相对距离
 * @returns path
 */
export function lineToPath(x1: number, y1: number, x2: number, y2: number) {
  if (isNaN(x1 - y1 + x2 - y2)) return "";
  x1 = x1 || 0;
  y1 = y1 || 0;
  x2 = x2 || 0;
  y2 = y2 || 0;
  return "M" + x1 + " " + y1 + " L" + x2 + " " + y2;
}

/** 矩形的转换为path；
 *
 * @param x 左上顶点x坐标
 * @param y 左上顶点y坐标
 * @param width 矩形宽度
 * @param height 矩形高度
 * @param rx x方向圆角半径
 * @param ry y方向圆角半径
 * @returns 矩形
 */
export function rectToPath(
  x: number,
  y: number,
  width: number,
  height: number,
  rx?: number,
  ry?: number
) {
  rx = rx || ry || 0;
  ry = ry || rx || 0;
  if (isNaN(x - y + width - height + rx - ry)) return "";
  rx = rx > width / 2 ? width / 2 : rx;
  ry = ry > height / 2 ? height / 2 : ry;
  let path = "";
  if (rx === 0 || ry === 0) {
    path = "M" + x + " " + y + "h" + width + "v" + height + "h" + -width + "z";
  } else {
    path =
      "M" +
      x +
      " " +
      (y + ry) +
      "a" +
      rx +
      " " +
      ry +
      " 0 0 1 " +
      rx +
      " " +
      -ry +
      "h" +
      (width - rx - rx) +
      "a" +
      rx +
      " " +
      ry +
      " 0 0 1 " +
      rx +
      " " +
      ry +
      "v" +
      (height - ry - ry) +
      "a" +
      rx +
      " " +
      ry +
      " 0 0 1 " +
      -rx +
      " " +
      ry +
      "h" +
      (rx + rx - width) +
      "a" +
      rx +
      " " +
      ry +
      " 0 0 1 " +
      -rx +
      " " +
      -ry +
      "z";
  }
  return path;
}

/** 椭圆的转换为path；
 * 圆可视为是一种特殊的椭圆
 * @param cx 圆形x坐标
 * @param cy 圆形y坐标
 * @param rx x方向半径
 * @param ry y方向半径
 * @returns path
 */
export function ellipseToPath(cx: number, cy: number, rx: number, ry: number) {
  if (isNaN(cx - cy + rx - ry)) return "";
  return (
    "M" +
    (cx - rx) +
    " " +
    cy +
    "a" +
    rx +
    " " +
    ry +
    " 0 1 0 " +
    2 * rx +
    " 0" +
    "a" +
    rx +
    " " +
    ry +
    " 0 1 0 " +
    -2 * rx +
    " 0" +
    "z"
  );
}

/** 折线的转换为path
 *
 * @param points [x1, y1, x2, y2, x3, y3 ...];
 * @returns path
 */
export function polylineToPath(points: number[]) {
  return "M" + points.slice(0, 2).join(" ") + "L" + points.slice(2).join(" ");
}

/** 多边形的转换为path；
 * polygon多边形会闭合
 * @param points [x1, y1, x2, y2, x3, y3 ...];
 * @returns path
 */
export function polygonToPath(points: number[]) {
  return (
    "M" + points.slice(0, 2).join(" ") + "L" + points.slice(2).join(" ") + "z"
  );
}

export function convertPathData(node: HTMLElement) {
  if (!node.tagName) return;
  // 匹配路径中数值的正则
  var regNumber = /[-+]?(?:\d*\.\d+|\d+\.?)(?:[eE][-+]?\d+)?/g;
  const tagName = node.tagName.toLowerCase();
  let path: string = "";
  switch (tagName) {
    case "path":
      path = node.getAttribute("d") as string;
      break;
    case "line":
      const x1 = Number(node.getAttribute("x1"));
      const y1 = Number(node.getAttribute("y1"));
      const x2 = Number(node.getAttribute("x2"));
      const y2 = Number(node.getAttribute("y2"));
      path = lineToPath(x1, y1, x2, y2);
      break;
    case "rect":
      const x = Number(node.getAttribute("x"));
      const y = Number(node.getAttribute("y"));
      const width = Number(node.getAttribute("width"));
      const height = Number(node.getAttribute("height"));
      const rect_rx =
        Number(node.getAttribute("rx")) || Number(node.getAttribute("ry")) || 0;
      const rect_ry =
        Number(node.getAttribute("ry")) || Number(node.getAttribute("rx")) || 0;
      path = rectToPath(x, y, width, height, rect_rx, rect_ry);
      break;
    case "circle":
      const circle_cx = Number(node.getAttribute("cx"));
      const circle_cy = Number(node.getAttribute("cy"));
      const r = Number(node.getAttribute("r"));
      path = ellipseToPath(circle_cx, circle_cy, r, r);
      break;
    case "ellipse":
      const ellipse_cx = Number(node.getAttribute("cx"));
      const ellipse_cy = Number(node.getAttribute("cy"));
      const ellipse_rx = Number(node.getAttribute("rx"));
      const ellipse_ry = Number(node.getAttribute("ry"));
      path = ellipseToPath(ellipse_cx, ellipse_cy, ellipse_rx, ellipse_ry);
      break;
    case "polygon":
    case "polyline":
      const points = (node.getAttribute("points")?.match(regNumber) || []).map(
        Number
      );
      if (points.length < 4) return;
      path = polygonToPath(points);
      break;
    default:
      break;
  }
  return path || "";
}
